package com.woniuxy.controller;


import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.config.AlipayConfig;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.woniuxy.commons.model.Result;
import com.woniuxy.commons.utils.BeanCopyUtil;
import com.woniuxy.commons.utils.CommonsUtil;
import com.woniuxy.commons.utils.DateUtil;
import com.woniuxy.commons.utils.OrderLogUtil;
import com.woniuxy.controller.form.*;
import com.woniuxy.service.DietOrderFoodService;
import com.woniuxy.service.DietOrderLogService;
import com.woniuxy.service.DietOrderService;
import com.woniuxy.service.dto.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sound.midi.Soundbank;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author psy
 * @since 2022-06-28
 */
@RestController
@RequestMapping("/dietOrder")
@Api(tags="订单接口")
public class DietOrderController {
    @Resource
    private DietOrderService dietOrderService;
    @Resource
    private DietOrderFoodService dietOrderFoodService;
    @Resource
    private DietOrderLogService dietOrderLogService;
    @Resource
    private RedisTemplate<String,String> sot;
    @PostMapping("/notify")
    @ApiOperation("支付宝异步回调，修改订单状态和同步订单日志")
    public Result changeOrderState(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
//            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        boolean signVerified = false; //调用SDK验证签名
        try {
            signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //——请在这里编写您的程序（以下代码仅作参考）——

	/* 实际验证过程建议商户务必添加以下校验：
	1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
	2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
	3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
	4、验证app_id是否为该商户本身。
	*/
        if(signVerified) {//验证成功
            //商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");

            if(trade_status.equals("TRADE_FINISHED")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意：
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
                System.out.println("支付失败");
            }else if (trade_status.equals("TRADE_SUCCESS")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意：
                //付款完成后，支付宝系统发送该交易状态通知
                System.out.println("支付成功");
                System.out.println("修改订单状态");
                String ordertime = CommonsUtil.getOrderCreateTime();
                //支付方式
                int payType=1;
                PayFinishForm payFinishForm=new PayFinishForm();
                payFinishForm.setOrderNum(out_trade_no);
                payFinishForm.setPayType(payType);
                payFinishForm.setState(1);
                //修改订单
                boolean b = dietOrderService.updateOrderByPayFinish(payFinishForm);
                System.out.println("修改订单状态成功");
                //修改订单日志
                OrderLogForm orderLogForm=new OrderLogForm();
                orderLogForm.setOrderNum(out_trade_no);
                orderLogForm.setOrderState(1);
                orderLogForm.setOperContent("完成付款");
                orderLogForm.setOperDate(ordertime);
                orderLogForm.setOperReason("付款成功");
                orderLogForm.setOperName("完成付款");
                String username="系统";
                orderLogForm.setOperUser(username);
                Boolean aBoolean = dietOrderLogService.addOrderLog(orderLogForm);
                System.out.println("新增订单日志成功");

            }

        }else {//验证失败
            System.out.println("验证失败");

            //调试用，写文本函数记录程序运行情况是否正常
            //String sWord = AlipaySignature.getSignCheckContentV1(params);
//            AlipayConfig.logResult(sWord);
        }
        return Result.success(200,"success",null);
    }

    /**
     * 商家接单
     * @param orderNum 接收前端传过来的订单编号
     * @return
     */
    @PutMapping("/storeacceptorder/{orderNum}")
    @ApiOperation("商家接单(默认商家配送)")
    @ApiImplicitParams({
            @ApiImplicitParam(name="orderNum",value="接收前端传过来的订单编号")
    })
    public Result storeAcceptOrder(@PathVariable("orderNum") String orderNum){
        System.out.println(orderNum);
        StoreAcceptOrderForm acceptOrderForm=new StoreAcceptOrderForm();
        acceptOrderForm.setOrderNum(orderNum);
        UserDetailsDto userDetailsDto = (UserDetailsDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        acceptOrderForm.setDispatching("商家配送");
        String storeTime = CommonsUtil.getOrderCreateTime();
        acceptOrderForm.setReceiveDate(storeTime);
        acceptOrderForm.setState(2);
        System.out.println(acceptOrderForm);
        boolean b = dietOrderService.storeAcceptOrder(acceptOrderForm);
        //同步日志
        OrderLogForm orderLog = OrderLogUtil.createOrderLog(orderNum, 2, "接单", "操作接单", "接单");
        Boolean aBoolean = dietOrderLogService.addOrderLog(orderLog);
        System.out.println("订单日志同步成功");
        return Result.success(200,"商家接单修改订单成功",null);
    }
    /**
     * 商家点击完成菜品等待配送
     * @param orderNum 接收前端传递的订单编号
     * @return
     */
    @PutMapping("/waitdispatching/{orderNum}")
    @ApiOperation("商家点击完成菜品等待配送")
    @ApiImplicitParams({
            @ApiImplicitParam(name="orderNum",value="接收前端传过来的订单编号")
    })
    public Result waitDispatching(@PathVariable String orderNum){
        boolean b = dietOrderService.waitDispatching(orderNum);
        //同步日志
        OrderLogForm orderLog = OrderLogUtil.createOrderLog(orderNum, 6, "等待配送", "菜品完成等待配送", "等待配送");
        Boolean aBoolean = dietOrderLogService.addOrderLog(orderLog);
        System.out.println("订单日志同步成功");
        return Result.success(200,"点击等待配送成功",null);
    }
    /**
     * 商家点击配送
     * @param orderNum 接收前端传递的订单号
     * @return
     */
    @PutMapping("/dispatching/{orderNum}")
    @ApiOperation("商家点击配送")
    @ApiImplicitParams({
            @ApiImplicitParam(name="orderNum",value="接收前端传过来的订单编号")
    })
    public Result storeDispatching(@PathVariable String orderNum){
        System.out.println(orderNum);
        StoreDispatchingForm storeDispatchingForm=new StoreDispatchingForm();
        storeDispatchingForm.setOrderNum(orderNum);
        UserDetailsDto userDetailsDto = (UserDetailsDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        storeDispatchingForm.setSendUser(userDetailsDto.getUsername());
        storeDispatchingForm.setSendPhone(userDetailsDto.getPhone());
        storeDispatchingForm.setSendAccount(userDetailsDto.getAccountId()+"");
        Long time=System.currentTimeMillis()+3*600000;
        String newTime = DateUtil.parseDateLong(time,"yyyy-MM-dd HH:mm:ss");
        storeDispatchingForm.setExpectReachDate(newTime);
        boolean b = dietOrderService.storeDispatching(storeDispatchingForm);
        //同步订单日志
        OrderLogForm orderLog = OrderLogUtil.createOrderLog(storeDispatchingForm.getOrderNum(), 3, "派送", "商家点击开始派送", "菜品已开始配送");
        Boolean aBoolean = dietOrderLogService.addOrderLog(orderLog);
        System.out.println("订单日志同步成功");
        return Result.success(200,"点击派送成功",null);
    }

    /**
     * 买家点击取消订单
     * @param orderNum 接收前端传递的订单号
     * @param operReason 接收前端传递的取消原因
     * @return
     */
    @PutMapping("/buycancelorder/{orderNum}/{operReason}")
    @ApiOperation("买家点击取消订单")
    @ApiImplicitParams({
            @ApiImplicitParam(name="orderNum",value="接收前端传过来的订单编号"),
            @ApiImplicitParam(name="operReason",value="接收前端传过来的买家取消订单原因")
    })
    public Result buyCancelOrder(@PathVariable String orderNum,@PathVariable String operReason){
        boolean buycancelorder = dietOrderService.buycancelorder(orderNum);
        //同步日志
        OrderLogForm orderLog = OrderLogUtil.createOrderLog(orderNum, 5, "取消订单", operReason, "取消订单");
        Boolean aBoolean = dietOrderLogService.addOrderLog(orderLog);
        System.out.println("订单日志同步成功");
        return Result.success(200,"买家取消订单成功",null);
    }

    /**
     * 商家不接单
     * @param orderNum 接收前端传递的订单号
     * @param operReason 接收前端传递的不接单原因
     * @return
     */
    @PutMapping("/storerefuse/{orderNum}/{operReason}")
    @ApiOperation("商家不接单")
    @ApiImplicitParams({
            @ApiImplicitParam(name="orderNum",value="接收前端传过来的订单编号"),
            @ApiImplicitParam(name="operReason",value="接收前端传递的不接单原因")
    })
    public Result storeRefuse(@PathVariable String orderNum,@PathVariable String operReason){
        boolean b = dietOrderService.storeRefuse(orderNum, operReason);
        //同步日志
        OrderLogForm orderLog = OrderLogUtil.createOrderLog(orderNum, 7, "商家不接单", operReason, "商家拒绝接单");
        Boolean aBoolean = dietOrderLogService.addOrderLog(orderLog);
        System.out.println("订单日志同步成功");
        return Result.success(200,"商家拒绝接单成功",null);
    }

    /**
     * 配送员拒绝配送
     * @param orderNum 接收前端传递的订单号
     * @param deliveryRefuseReason 接收前端传递的不配送原因
     * @return
     */
    @PutMapping("/conrierrefuse/{orderNum}/{deliveryRefuseReason}")
    @ApiOperation("配送员拒绝配送")
    @ApiImplicitParams({
            @ApiImplicitParam(name="orderNum",value="接收前端传过来的订单编号"),
            @ApiImplicitParam(name="deliveryRefuseReason",value="接收前端传递的不配送原因")
    })
    public Result conrierRefuse(@PathVariable String orderNum,@PathVariable String deliveryRefuseReason){
        boolean b = dietOrderService.conrierRefuse(orderNum, deliveryRefuseReason);
        //同步日志
        OrderLogForm orderLog = OrderLogUtil.createOrderLog(orderNum, 8, "配送员拒绝配送", deliveryRefuseReason, "配送员拒绝配送");
        Boolean aBoolean = dietOrderLogService.addOrderLog(orderLog);
        System.out.println("订单日志同步成功");
        return Result.success(200,"配送驳回成功",null);
    }

    /**
     * 订单完成,商家点击已完成，评价开始倒计时
     * @param orderNum 接收前端传递的订单号
     * @param storeId 接收前端传递的商家ID
     * @return
     */
    @PutMapping("/finishorder/{orderNum}/{storeId}")
    @ApiOperation("订单完成,商家点击已完成，评价开始倒计时")
    @ApiImplicitParams({
            @ApiImplicitParam(name="orderNum",value="接收前端传过来的订单编号"),
            @ApiImplicitParam(name="storeId",value="接收前端传递的商家ID")
    })
    public Result finishOrder(@PathVariable String orderNum,@PathVariable Long storeId){
        boolean b = dietOrderService.finishOrder(orderNum);
        sot.opsForValue().setIfAbsent(storeId+"DD"+orderNum,orderNum,12, TimeUnit.HOURS);
        //同步日志
        OrderLogForm orderLog = OrderLogUtil.createOrderLog(orderNum, 4, "订单完成", "完成订单", "订单完成");
        Boolean aBoolean = dietOrderLogService.addOrderLog(orderLog);
        System.out.println("订单日志同步成功");
        return Result.success(200,"订单完成",null);
    }

    /**
     * 根据买家ID来查询对应订单
     * @return 返回对应用户的所有订单
     */
    @GetMapping("/getorderbycustomerid")
    @ApiOperation("根据买家ID来查询对应订单")
    public Result getOrderByCustomerId(OrderCustomerLookForm orderCustomerLookForm){
        UserDetailsDto userDetailsDto = (UserDetailsDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long id = userDetailsDto.getId();
        orderCustomerLookForm.setCustomerId(id);
        Page<OrderCustomerDto> orderByCustomerId = dietOrderService.getOrderByCustomerId(orderCustomerLookForm);
        return Result.success(200,"加载用户订单成功",orderByCustomerId);
    }
    /**
     * 根据订单编号查询对应订单详情
     * @param orderNum 接收订单编号
     * @param storeName 接收商家名称，用来查询redis中商家的配送费和打包费
     * @return 返回对应订单的订单详情
     */
    @GetMapping("/getorderdetailsbyordernum")
    @ApiOperation("根据订单编号查询对应订单详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderNum",value = "订单编号"),
            @ApiImplicitParam(name = "storeName",value = "商家名称")
    })
    public Result getOrderDetailsByOrderNum(String orderNum,String storeName) throws JsonProcessingException {
        OrderDetailsDto orderDetailsDto = dietOrderService.getOrderDetailsByOrderNum(orderNum, storeName);
        return Result.success(200,"加载订单详情成功",orderDetailsDto);
    }

    /**
     * 根据卖家ID查询对应订单
     * @return 返回对应商家的全部订单信息
     */
    @GetMapping("/getorderbystoreid")
    @ApiOperation("根据卖家ID查询对应订单，支持状态条件查询和订餐人、联系电话模糊查询")
    public Result getOrderByStoreId(OrderStoreLookForm orderStoreLookForm){
        UserDetailsDto userDetailsDto = (UserDetailsDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long id = userDetailsDto.getId();
        orderStoreLookForm.setStoreId(id);
        Page<OrderStoreDto> orderByStoreId = dietOrderService.getOrderByStoreId(orderStoreLookForm);
        return Result.success(200,"加载商家订单成功",orderByStoreId);
    }

    /**
     * 再来一单，跳购物车
     * @param orderNum 订单编号
     * @param storeName 商家名称
     * @return
     */
    @GetMapping("/orderagain")
    @ApiOperation("再来一单，跳购物车")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderNum",value = "订单编号"),
            @ApiImplicitParam(name = "storeName",value = "商家名称")
    })
    public Result orderAgain(String orderNum,String storeName){
        UserDetailsDto userDetailsDto = (UserDetailsDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long id = userDetailsDto.getId();
        AllCartListDto allCartListDto = dietOrderService.orderAgain(id, orderNum, storeName);
        return Result.success(200,"添加购物车成功",allCartListDto);
    }


}

